package com.joinway.framework.support.logging.service.impl;

import java.util.Map;
import java.util.Map.Entry;
import java.util.Set;
import java.util.WeakHashMap;

import org.apache.commons.lang3.ArrayUtils;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.joinway.framework.bean.logging.type.EventLevel;
import com.joinway.framework.core.utils.AppEnv;
import com.joinway.framework.extension.cipher.AES;
import com.joinway.framework.extension.net.mail.MailClient;
import com.joinway.framework.support.logging.service.IEventHandler;

public class ErrorEmailEventHandler implements IEventHandler {

	private final static Logger log = LoggerFactory.getLogger(ErrorEmailEventHandler.class);

	private final static String CIPHER_KEY = "A long time a...";
	
	protected MailClient mailClient;
	
	protected String[] mailTo;
	
	protected boolean smart = false;
	
	protected boolean passwordEncrypt = false;
	
	protected Map<String, String> events = new WeakHashMap<>();
	
	public static void main(String[] args) throws Exception {
		if(ArrayUtils.isEmpty(args)){
			System.out.println("please input plain text password");
			return;
		}
		
		System.out.println(AES.encrypt(args[0], CIPHER_KEY));
//		System.out.println(AES.decrypt(AES.encrypt(args[0], CIPHER_KEY), CIPHER_KEY));
	}
	
	public ErrorEmailEventHandler(String smtp, String user, String password, String[] mailTo) throws Exception {
		String pwd = passwordEncrypt ? AES.decrypt(password, CIPHER_KEY) : password;
		this.mailClient = new MailClient(smtp, user, pwd);
		this.mailTo = mailTo;
	}
	
	@Override
	public void handleInfoEvent(Map<String, Object> row) {
		// do nothing
	}

	@Override
	public void handleWarnEvent(Map<String, Object> row) {
		// do nothing
	}

	@Override
	public void handleErrorEvent(Map<String, Object> row) {
		sendNoticeMail(EventLevel.Error, row);
	}

	@Override
	public void handleFatalEvent(Map<String, Object> row) {
		sendNoticeMail(EventLevel.Fatal, row);
	}
	
	protected void sendNoticeMail(EventLevel level, Map<String, Object> row){
		String subject = constructMailSubject(level, row);
		String content = constructMailContent(level, row);
		
		String key = StringUtils.join(row.get("event_id"), row.get("event_key"), row.get("key_type"), row.get("message"));
		
		try {
			if(smart){
				if(StringUtils.isBlank(events.get(key))){
					events.put(key, key);
					mailClient.sendTextMessage(subject, content, mailTo);
				}
			}else{
				mailClient.sendTextMessage(subject, content, mailTo);
			}
		} catch (Exception e) {
			log.error("failed to send envent notice mail " + subject, e);
		}
	}

	protected String constructMailSubject(EventLevel level, Map<String, Object> row){
		return StringUtils.join("[" , getAppEnv(), "] ", row.get("app_id"), " on [" , row.get("host_name"), "] of [", row.get("node"), "] Raised ", level, " Event - "
				, row.get("event_id"), "::", StringUtils.trimToEmpty(String.valueOf(row.get("message"))));
	}
	
	protected String constructMailContent(EventLevel level, Map<String, Object> row){
		StringBuilder sb = new StringBuilder();
		
		Set<Entry<String, Object>> entries = row.entrySet();
		for(Entry<String, Object> entry : entries){
			sb.append(entry.getKey()).append(":\t").append(entry.getValue()).append("\n");
		}
		
		return sb.toString();
	}
	
	protected String getAppEnv(){
		String env = AppEnv.getEnvName();
		return StringUtils.isBlank(env) ? "test" : env;
	}
	
	public String[] getMailTo() {
		return mailTo;
	}

	public void setMailTo(String[] mailTo) {
		this.mailTo = mailTo;
	}

	public boolean isSmart() {
		return smart;
	}

	public void setSmart(boolean smart) {
		this.smart = smart;
	}

	public boolean isPasswordEncrypt() {
		return passwordEncrypt;
	}

	public void setPasswordEncrypt(boolean passwordEncrypt) {
		this.passwordEncrypt = passwordEncrypt;
	}
}

